/*
 * Copyright (C) 2012 mAPPn.Inc
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.mol.market.ui.core;

import java.util.ArrayList;
import java.util.HashMap;

import android.content.Context;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AbsListView.LayoutParams;
import android.widget.LinearLayout;
import android.widget.ListView;

import com.mol.market.R;
import com.mol.market.demo.widget.AbsListViewFragment;
import com.mol.market.demo.widget.LazyLoadAbsListViewFragment;

/**
 * 可以让ListView呈现GridView的布局。
 * <hr>
 * notice：不要对AbsListView使用OnItemClickListener，如果需要，对Adapter
 *         使用GridAdapter.OnItemClickListener
 * <br>
 * advice: 如果你的AbsListView并没有HeaderView或者FooterView，强烈建议放弃使用这个Adapter，
 *         转而使用GridView配合CommonAdapter.因为这个Adapter的性能并不如GridView本身更好。
 * @author Chaos    
 * @Description 格子布局
 * @date 2012-12-17 
 */
public class GridAdapter extends LazyLoadAdapter
                implements OnClickListener{

    private int mColumns = 1;
    private Context mContext;
    private LazyLoadAbsListViewFragment mFm;
    
    private OnItemClickListener mOnItemClickListener;
    
    private boolean mIsOpenLazyLoad = true;
    /**
     * @param fragment
     * @param data
     * @param resource
     * @param from
     * @param to
     */
    public GridAdapter(LazyLoadAbsListViewFragment fragment,
            ArrayList<HashMap<String, Object>> data, int resource, String[] from, int[] to) {
        super(fragment, data, resource, from, to);
        this.mContext = fragment.getActivity();
        this.mFm      = fragment;
        
        //close super lazyload
        super.closeLazyLoad();
        
        forcedAdvice(fragment);
        
        //check
        if(mFm.getAbsListView() != null && mFm.getAbsListView().getOnItemClickListener() != null){
            throw new RuntimeException("you must use GridAdapter.OnItemClickListener");
        }
    }
    
    /**
     *  建立GridAdapter的时候，有两种情况是必须禁止的。
     *  1.当AbsListView设置了onItemClickListener的时候，是必须禁止的，原因在于AbsListView的Item已经和
     *    实际的Item不符，它们描述的本质不同。
     *  2.当AbsListView是ListView，并且没有HeaderView和FooterView的时候，必须使用GridView，因为即使使用
     *    Adapter实现，性能一定不如用GirdView。
     *  所以，必须在建立Adapter的时候就迅速失败，以免造成更多的问题。
     *  by chaos at 2013/1/24
     * @param 
     * @return 
     * @throws
     */
    public void forcedAdvice(AbsListViewFragment fragment){
        
        //Suggest using GridView
        if(fragment.getAbsListView() instanceof ListView
                && !fragment.containFooterView()
                && !fragment.containsHeaderView()){
            throw new IllegalArgumentException(
                    "You use the ListView is totally unnecessary! Use the GridView and CommonAdapter replace it");
        }
        
        //Wrong use OnItemClickListener
        if(fragment.getAbsListView() != null && fragment.getAbsListView().getOnItemClickListener() != null){
            throw new IllegalArgumentException(
                    "You have to equip this adapter with this listener");
        }
        
    }
    
    public void setNumColumns(int columns){
        this.mColumns = columns;
    }
    
    public int getNumColumns(){
        return mColumns;
    }
    
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        return getGridView(position, convertView, parent);
    }
    
    public View getGridView(int position,View convertView,ViewGroup parent){
        
        if(mIsOpenLazyLoad){
            doLazyLoad(position, mFm);
        }
        
        if(mColumns == 1){
            View child = super.getView(position, convertView, parent);
            setOnItemClickListenerIfNeed(child, position, position);
            return child;
        }else{
            ViewGroup root = null;
            if(convertView != null && convertView instanceof ViewGroup){
                root = (ViewGroup) convertView;
            }else{
                root = createRoot();
                root.setClickable(false);
                root.setFocusable(false);
            }
            
            //columns = 3
            //pos --> real pos
            //0   --> 0 1 2
            //1   --> 3 4 5
            //2   --> 6 7 8
            //so do this
            return bindView(root, position);
        }
    }
    
    private void doLazyLoad(int position,LazyLoadAbsListViewFragment fragment){
        if(position == getCount() - 1){
            fragment.doLazyLoad();
        }
    }
    
    private View bindView(ViewGroup root, int position) {

        final int childCount = root.getChildCount();

        for (int i = 0; i < mColumns; i++) {
            // real position
            int index = mColumns * position + i;
            // 不足一行时，直接返回现有状态
            if (index == super.getCount()) {
                // fix bug : root是有可能是系统缓存的root，这里直接返回root将导致如果此行数量
                // 不够columns，就会使用缓存的root里的child，为了避免这个问题，必须
                // 将缓存的child移除。
                // by Chaos at 2012-12-17
                removeCacheChild(root, index);
                break;
            }

            View child = super.getView(index, root.getChildAt(i), root);

            setOnItemClickListenerIfNeed(child, position, index);
            
            if (childCount == mColumns) {
                // root已经包含了Item，就没有必要继续添加了。
                continue;
            } else {
                if (i == 0 && childCount != 0) {
                    // 如果root已经包含item，但是并不全，这里就移除重新添加
                    // FIXME 也许还有更好的方案
                    root.removeAllViews();
                }
                LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
                // LinearLayout.LayoutParams.WRAP_CONTENT,
                        mFm.getWidth() / mColumns, LinearLayout.LayoutParams.WRAP_CONTENT);
                child.setFocusable(true);
                child.setClickable(true);
                if (child instanceof ViewGroup) {
                    ((ViewGroup) child)
                            .setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
                }
                root.addView(child, lp);
            }
        }
        return root;
    }
    
    private void removeCacheChild(ViewGroup root,int index){
        int realColumns = (index - 1) % mColumns;
        int moveCount   = (mColumns - 1) - realColumns;
        
        for (int i = 0; i < moveCount; i++) {
            final View child = root.getChildAt((mColumns - 1 - i));
            if(child != null){
                root.removeView(child);
            }
        }
    }
    
    private boolean setOnItemClickListenerIfNeed(View child,int pos,int realPos) {
        if(mOnItemClickListener == null){
            return false;
        }
        child.setOnClickListener(this);
        child.setTag(R.id.pos, pos);
        child.setTag(R.id.realPos, realPos);
        return true;
    }
    
    @Override
    public int getCount() {
        int count = (int) Math.ceil(super.getCount() / (double)mColumns);
        return count;
    }
    
    protected ViewGroup createRoot(){
        LinearLayout root = new LinearLayout(mContext);
        root.setOrientation(LinearLayout.HORIZONTAL);
        LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
        root.setLayoutParams(lp);
        return root;
    }
    
    @Override
    public void onClick(View v) {
        
        if(mOnItemClickListener == null){
            return ;
        }
        
        Object pos     = v.getTag(R.id.pos);
        Object realPos = v.getTag(R.id.realPos); 
        
        if(pos != null && realPos != null){
            mOnItemClickListener.onItemClick((Integer)pos, (Integer)realPos,
                    (HashMap<String, Object>) getItem((Integer)realPos));
        }
    }
    
    public void setOnItemClickListener(OnItemClickListener listener){
        this.mOnItemClickListener = listener;
    }
    
    public static interface OnItemClickListener{
        public void onItemClick(int pos,int realPos,HashMap<String, Object> item);
    }
    
    /**
     * 首先，我们必须确保父类的Adapter关闭了延迟加载，
     * 其次，我们本身也要实现开关功能。
     * <br>
     * {@link #GridAdapter(LazyLoadAbsListViewFragment, ArrayList, int, String[], int[])}中关闭了父类的延迟加载功能，
     * 并且子类实现了自己延迟加载开关的功能
     */
    @Override
    public void closeLazyLoad() {
       this.mIsOpenLazyLoad = false;
    }
    
    @Override
    public void openLazyLoad() {
        this.mIsOpenLazyLoad = true;
    }
}
